function Holdings = weights2holdings(Values, Weights, Prices)
%WEIGHTS2HOLDINGS Convert portfolio value and weights into portfolio holdings.
% Convert portfolio weights into portfolio holdings, where it is assumed that
% the weights satisfy a non-zero budget constraint.
%
%	Holdings = weights2holdings(Values, Weights, Prices);
%
% Inputs:
%	Values - Either a NUMPORTS vector with NUMPORTS total portfolio values for
%		each portfolio or a scalar value to be applied to all portfolios.
%	Weights - A NUMPORTS x NUMASSETS matrix with the weights of NUMPORTS
%		portfolios that contain NUMASSETS assets.
%	Prices - A NUMASSETS vector with NUMASSETS asset prices.
%
% Outputs:
%	Holdings - A NUMPORTS x NUMASSETS matrix that contains the holdings of
%		NUMPORTS portfolios that contain NUMASSETS assets.
%
% Notes -
%	Note that the weights sum to the value of a Budget constraint, which is
%	usually 1.
%
%   This routine does not create round-lot positions, i.e., Holdings are
%   floating-point values.
%
%	See also HOLDINGS2WEIGHTS

%	Copyright 2005 The MathWorks, Inc.
%	$Revision: 1.1.6.1 $ $Date: 2005/11/11 16:21:44 $

if nargin < 3
	error('Finance:weights2holdings:MissingInputArg', ...
		'Missing required input arguments Values, Weights, or Prices.');
end

if isempty(Values)
	error('Finance:weights2holdings:EmptyValuesVector', ...
		'Values vector is empty - cannot continue.');
end

if isempty(Weights)
	error('Finance:weights2holdings:EmptyWeightsMatrix', ...
		'Weights matrix is empty - cannot continue.');
end

if isempty(Prices)
	error('Finance:weights2holdings:EmptyPricesVector', ...
		'Prices vector is empty - cannot continue.');
end

[NumPorts, NumAssets] = size(Weights);

if isvector(Values)
	Values = Values(:);
	i = size(Values,1);
	if (i == 1)
		Values = repmat(Values,NumPorts,1);
	elseif (i ~= NumPorts)
		error('Finance:weights2holdings:InconsistentDims', ...
			'Values should be either a scalar or a vector with NumPorts elements.');
	end
else
	error('Finance:weights2holdings:InconsistentDims', ...
		'Prices vector is empty - cannot continue.');
end	

if isvector(Prices)
	Prices = Prices(:)';
	if (numel(Prices) ~= NumAssets)
		error('Finance:weights2holdings:InconsistentDims', ...
			'Invalid number of asset Prices.');
	end
else
	error('Finance:weights2holdings:InvalidPriceVector', ...
		'Prices should be a vector - cannot continue.');
end

Holdings = zeros(NumPorts, NumAssets);

for i = 1:NumPorts
	Budget = sum(Weights(i,:));
	if (Budget == 0.0)
		error('Finance:weights2holdings:InvalidBudget', ...
			'Weights sum to zero - cannot form holdings.');
	end
	Holdings(i,:) = (1.0/Budget) .* Values(i) .* Weights(i,:) ./ Prices;
end
